from math import *
from string import *
from time import *

# Node for each location
# each node gets a unique number via genNum
# neighbors are to the N,E,S,W; stored by their node numbers
# image is the visual identifier of the location; some locations
#     do not have images, are only along the path to other locations
class worldNode:
    def __init__(self,num,N,E,S,W,image,typ):
        self.__num = num
        self.__N = N
        self.__E = E
        self.__S = S
        self.__W = W
        self.__image = image
        self.__typ = typ

    def set_name(self,num):
        self.__num = num

    def set_N(self,N):
        self.__N = N

    def set_E(self,E):
        self.__E = E

    def set_S(self,S):
        self.__S = S

    def set_W(self,W):
        self.__W = w

    def set_image(self,image):
        self.__image = image

    def set_typ(self,typ):
        self.__typ = typ

    def get_num(self):
        return self.__num

    def get_N(self):
        return self.__N

    def get_E(self):
        return self.__E

    def get_S(self):
        return self.__S

    def get_W(self):
        return self.__W

    def get_image(self):
        return self.__image

    def get_typ(self):
        return self.__typ

# Node for simMyro
#  loc - keeps track of simMyro's current location
#  facing - keeps track of direction in which simMyro is facing
#  seeing - is a copy of the image simMryo sees at this that location
#  gazing - is a copy of the image simMryo sees in the direction it is facing
class aSimMyro:
    def __init__(self,loc, facing, seeing, gazing,ergs):
        self.__loc = loc
        self.__facing = facing
        self.__seeing = seeing
        self.__gazing = gazing
        self.__ergs = ergs

    def set_loc(self,loc):
        self.__loc = loc

    def set_facing(self,facing):
        self.__facing = facing

    def set_seeing(self,seeing):
        self.__seeing = seeing

    def set_gazing(self,gazing):
        self.__gazing = gazing

    def set_ergs(self,ergs):
        self.__ergs = ergs

    def get_loc(self):
        return self.__loc

    def get_facing(self):
        return self.__facing

    def get_seeing(self):
        return self.__seeing

    def get_gazing(self):
        return self.__gazing

    def get_ergs(self):
        return self.__ergs

def genNum():
    n = -1
    while True:
        n += 1
        yield n

def setWorld():
    worldInfo = open('simWorld.txt','r')
    ww = worldInfo.readline()
    ww = ww.rstrip('\n')
    ww = int(ww)
    world = []
    for loc in range(ww):
        infoList = readIntegers(worldInfo)
        if loc != infoList[0]:
            print "Mismatch of loc number", loc,infoList[0]
        north = infoList[1]
        east = infoList[2]
        south = infoList[3]
        west = infoList[4]
        idimageName = worldInfo.readline()
        idimageName = idimageName.rstrip('\n')
        idimage = makePicture(idimageName)
        nodeType = worldInfo.readline()
        nodeType = nodeType.rstrip('\n')
        newLoc = worldNode(loc,north,east,south,west,idimage,nodeType)
        world.append(newLoc)
    return world

def printLoc(loc):
    print "Enter printLoc"
    print world[loc].get_num()
    print world[loc].get_N()
    print world[loc].get_E()
    print world[loc].get_S()
    print world[loc].get_W()
    show(world[loc].get_image())

def readIntegers(intFile):
    row = intFile.readline()
    row = row.rstrip('\n')
    row = toInt(row.split())
    return row

def toInt(sList):
    for i in range(len(sList)):
        sList[i] = int(sList[i])
    return sList

def initSim():
    return simMyro.get_seeing(),simMyro.get_gazing(),simMyro.get_ergs()

def go(dist):
    newLoc = getNewLoc(dist)
    print 'New location',newLoc
#    printLoc(newLoc)
    eCost = dist
    if newLoc > -1:
        locType = world[newLoc].get_typ()
        if locType == 'X':
            eCost += 5
        ergs = simMyro.get_ergs() - eCost
        if ergs > -1:
            simMyro.set_loc(newLoc)
            see = world[newLoc].get_image()
            simMyro.set_seeing(see)
            gaze = getGazing(newLoc,simMyro.get_facing())
            simMyro.set_gazing(gaze)
            if locType == 'E':
                increase = min(30,75-ergs)
                ergs += increase
                eCost -= increase
            return [see,gaze,-eCost]
        else:
            return[False,False,False]
    else:
        return [False,False,False]

def R90():
    direction = simMyro.get_facing()
    if direction == "N":
        direction = "E"
    elif direction == "E":
        direction = "S"
    elif direction == "S":
        direction = "W"
    elif direction == "W":
        direction = "N"
    else:
        print "ERROR - direction not NSEW"
    simMyro.set_facing(direction)
    gaze = getGazing(simMyro.get_loc(),direction)
    simMyro.set_gazing(gaze)
    return gaze

def L90():
    direction = simMyro.get_facing()
    if direction == "N":
        direction = "W"
    elif direction == "W":
        direction = "S"
    elif direction == "S":
        direction = "E"
    elif direction == "E":
        direction = "N"
    else:
        print "ERROR - direction not NSEW"
    simMyro.set_facing(direction)
    gaze = getGazing(simMyro.get_loc(),direction)
    simMyro.set_gazing(gaze)
    return gaze

def getNewLoc(dist):
    direction = simMyro.get_facing()
    loc = simMyro.get_loc()
    while loc > -1 and dist > 0:
        dist -= 1
        loc = getNeighbor(loc,direction)
    if loc > -1:
        return loc
    else:
        return False

def getNeighbor(loc,direction):
    if direction == "N":
        return world[loc].get_N()
    elif direction == "E":
        return world[loc].get_E()
    elif direction == "S":
        return world[loc].get_S()
    elif direction == "W":
        return world[loc].get_W()
    else:
        print "ERROR - direction not NSEW"
        return False

# Old version of getGazing, when blank image was not stored
def getGazingOLD(loc,direction):
    neighbor = getNeighbor(loc,direction)
    print loc,direction, neighbor
    if neighbor < 0:
        return wall
    else:
        imageHere = world[neighbor].get_image()
        if imageHere:
            return halve2(imageHere)
        else:
            return halve2(getGazing(neighbor,direction))

def getGazing(loc,direction):
    neighbor = getNeighbor(loc,direction)
    print loc,direction, neighbor
    if neighbor < 0:
        return wall
    else:
        nghTyp = world[neighbor].get_typ()
        if nghTyp != 'w':
            imageHere = world[neighbor].get_image()
            return halve2(imageHere)
        else:
            return halve2(getGazing(neighbor,direction))

def meanColor(pic):
    allR = 0.0
    allG = 0.0
    allB = 0.0
    w,h = picSize(pic)
    numPixels = w*h
    for rpx in range(h):
        for cpx in range(w):
            r,g,b = getRGB(getPixel(pic,cpx,rpx))
            allR += r
            allG += g
            allB += b
    return allR/numPixels,allG/numPixels,allB/numPixels

# pauses n seconds
def pause(n):
    begin = time()
    now = time()
    while now-begin < n:
        now = time()

# Check 8 pixels of a diagonal of pic to see if it matches the "wall"
def isWall(pic):
    r,g,b = 101,75,50
    isw = True
    row = 0
    col = 0
    while isw and col < 240 and row < 320:
        pr,pg,pb = getRGB(getPixel(pic,row,col))
        isw = (r == pr) and (g == pg) and (b == pb)
        row += 40
        col += 30
    return isw

# Check 40 pixels of a diagonal of pic1 vs. pic2 to see whether they are roughly the same
def rufSame(pic1,pic2):
    same = True
    row = 0
    col = 0
    while same and col < 240 and row < 320:
        r1,g1,b1 = getRGB(getPixel(pic1,row,col))
        r2,g2,b2 = getRGB(getPixel(pic2,row,col))
        isw = (r1 == r2) and (g1 == g2) and (b1 == b2)
        row += 8
        col += 6
    return isw

def expand(mpic):
    newpic = makePicture(320,240)
    for row in range(192):
        for col in range(256):
            pixel = getPixel(newpic,col,row)
            r,g,b = getRGB(getPixel(mpic,col,row))
            setRGB(pixel,(r,g,b))
    for row in range(192):
        for col in range(256,320):
#            print row,col
            pixel = getPixel(newpic,col,row)
            r,g,b = getRGB(getPixel(mpic,255,row))
            setRGB(pixel,(r,g,b))
    for row in range(192,240):
        for col in range(320):
            pixel = getPixel(newpic,col,row)
            r,g,b = getRGB(getPixel(newpic,col,191))
            setRGB(pixel,(r,g,b))
    return newpic
    
def wallize(pic,mR,mG,mB):
    w,h = picSize(pic)
    numPixels = w*h
    for rpx in range(h):
        for cpx in range(w):
            pixel = getPixel(pic,cpx,rpx)
            setRGB(pixel,(mR,mG,mB))

def picSize(pic):
    allPixels = getPixels(pic)
    pixelList = []
    for pixel in allPixels:
        pixelList.append(pixel)
    if len(pixelList) == 76800:
        return 320,240
    else:
        return 256,192

# Turns myro.graphics.Picture into one half the size with white space taking up
#   remainder
def halve2(p):
    w,h = picSize(p)
    newP = makePicture(w,h)
    tempP = makePicture(w,h)
    for rpx in range(w):
        offset = h/4
        for cpx in range(0,h,2):
            pixel1 = getPixel(p,rpx,cpx)
            r1,g1,b1 = getRGB(pixel1)
            pixel2 = getPixel(p,rpx,cpx+1)
            r2,g2,b2 = getRGB(pixel2)
            nupixel = getPixel(tempP,rpx,offset+cpx/2)
            nur = round((r1+r2+0.0)/2)
            nug = round((g1+g2+0.0)/2)
            nub = round((b1+b2+0.0)/2)            
            setRGB(nupixel,(nur,nug,nub))
    for cpx in range(h):
        offset = w/4
        for rpx in range(0,w,2):
            pixel1 = getPixel(tempP,rpx,cpx)
            r1,g1,b1 = getRGB(pixel1)
            pixel2 = getPixel(tempP,rpx+1,cpx)
            r2,g2,b2 = getRGB(pixel2)
            nupixel = getPixel(newP,offset+rpx/2,cpx)
            nur = round((r1+r2+0.0)/2)
            nug = round((g1+g2+0.0)/2)
            nub = round((b1+b2+0.0)/2)            
            setRGB(nupixel,(nur,nug,nub))
    return newP

# Turns myro.graphics.Picture into one half the size with white space taking up
#   remainder
def halve(p,hp):
    w,h = picSize(p)
    tempP = makePicture(w,h)
    for rpx in range(w):
        offset = h/4
        for cpx in range(0,h,2):
            pixel1 = getPixel(p,rpx,cpx)
            r1,g1,b1 = getRGB(pixel1)
            pixel2 = getPixel(p,rpx,cpx+1)
            r2,g2,b2 = getRGB(pixel2)
            nupixel = getPixel(tempP,rpx,offset+cpx/2)
            nur = round((r1+r2+0.0)/2)
            nug = round((g1+g2+0.0)/2)
            nub = round((b1+b2+0.0)/2)            
            setRGB(nupixel,(nur,nug,nub))
    for cpx in range(h):
        offset = w/4
        for rpx in range(0,w,2):
            pixel1 = getPixel(tempP,rpx,cpx)
            r1,g1,b1 = getRGB(pixel1)
            pixel2 = getPixel(tempP,rpx+1,cpx)
            r2,g2,b2 = getRGB(pixel2)
            nupixel = getPixel(hp,offset+rpx/2,cpx)
            nur = round((r1+r2+0.0)/2)
            nug = round((g1+g2+0.0)/2)
            nub = round((b1+b2+0.0)/2)            
            setRGB(nupixel,(nur,nug,nub))
